|
CallGraph
|
00001 #include "callgraph.h" 00002 #include "uisettingsdlg.h" 00003 #include "uicallgraphpanel.h" 00004 #include "toolbaricons.h" 00005 #include <wx/xrc/xmlres.h> 00006 #include <wx/artprov.h> 00007 #include "workspace.h" 00008 #include "string.h" 00009 #include <wx/image.h> 00010 #include <wx/bitmap.h> 00011 #include <wx/aboutdlg.h> 00012 00017 static CallGraph* thePlugin = NULL; 00018 00019 //Define the plugin entry point 00020 extern "C" EXPORT IPlugin *CreatePlugin(IManager *manager) 00021 { 00022 if (thePlugin == 0) { 00023 thePlugin = new CallGraph(manager); 00024 } 00025 return thePlugin; 00026 } 00027 00028 wxString wxbuildinfo() 00029 { 00030 wxString wxbuild(wxVERSION_STRING); 00031 00032 #if defined(__WXMSW__) 00033 wxbuild << _T("-Windows"); 00034 #elif defined(__UNIX__) 00035 wxbuild << _T("-Linux"); 00036 #endif 00037 00038 #if wxUSE_UNICODE 00039 wxbuild << _T("-Unicode build"); 00040 #else 00041 wxbuild << _T("-ANSI build"); 00042 #endif 00043 00044 return wxbuild; 00045 } 00046 00047 extern "C" EXPORT PluginInfo GetPluginInfo() 00048 { 00049 PluginInfo info; 00050 info.SetAuthor(wxT("Václav Špruček, Tomas Bata University in Zlin, www.fai.utb.cz")); 00051 info.SetName(wxT("Call Graph")); 00052 info.SetDescription(wxT("Create application call graph from profiling information provided by gprof tool.")); 00053 info.SetVersion(wxT("v1.0")); 00054 return info; 00055 } 00056 00057 extern "C" EXPORT int GetPluginInterfaceVersion() 00058 { 00059 return PLUGIN_INTERFACE_VERSION; 00060 } 00061 00062 CallGraph::CallGraph(IManager *manager) 00063 : IPlugin(manager) 00064 { 00065 m_longName = wxT("Create application call graph from profiling information provided by gprof tool."); 00066 m_shortName = wxT("CallGraph"); 00067 00068 m_mgr->GetTheApp()->Connect( XRCID("cg_settings"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CallGraph::OnSettings ), NULL, this ); 00069 m_mgr->GetTheApp()->Connect( XRCID("cg_about"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CallGraph::OnAbout ), NULL, this ); 00070 00071 m_mgr->GetTheApp()->Connect( XRCID("cg_show_callgraph"), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( CallGraph::OnShowCallGraph ), NULL, this ); 00072 00073 stvariables::InicializeStatic(); 00074 //inicialize paths for standard and stored paths for this plugin 00075 GetDotPath(); 00076 GetGprofPath(); 00077 } 00078 00079 CallGraph::~CallGraph() 00080 { 00081 m_mgr->GetTheApp()->Disconnect( XRCID("cg_settings"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CallGraph::OnSettings ), NULL, this ); 00082 m_mgr->GetTheApp()->Disconnect( XRCID("cg_about"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( CallGraph::OnAbout ), NULL, this ); 00083 00084 m_mgr->GetTheApp()->Disconnect( XRCID("cg_show_callgraph"), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( CallGraph::OnShowCallGraph ), NULL, this ); 00085 } 00086 00087 clToolBar *CallGraph::CreateToolBar(wxWindow *parent) 00088 { 00089 //Create the toolbar to be used by the plugin 00090 clToolBar *tb(NULL); 00091 00092 // First, check that CodeLite allows plugin to register plugins 00093 if (m_mgr->AllowToolbar()) { 00094 // Support both toolbars icon size 00095 int size = m_mgr->GetToolbarIconSize(); 00096 00097 // Allocate new toolbar, which will be freed later by CodeLite 00098 tb = new clToolBar(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, clTB_DEFAULT_STYLE); 00099 00100 // Set the toolbar size 00101 tb->SetToolBitmapSize(wxSize(size, size)); 00102 00103 // Add tools to the plugins toolbar. You must provide 2 sets of icons: 24x24 and 16x16 00104 if (size == 24) { 00105 tb->AddTool(XRCID("cg_show_callgraph"), _("Show call graph"), cg24_icon_xpm, _("Show call graph for selected/active project"), wxITEM_NORMAL); 00106 } else { 00107 tb->AddTool(XRCID("cg_show_callgraph"), _("Show call graph"), cg16_icon_xpm, _("Show call graph for selected/active project"), wxITEM_NORMAL); 00108 } 00109 tb->Realize(); 00110 } 00111 return tb; 00112 } 00113 00114 void CallGraph::CreatePluginMenu(wxMenu *pluginsMenu) 00115 { 00116 00117 // You can use the below code a snippet: 00118 wxMenu *menu = new wxMenu(); 00119 wxMenuItem *item(NULL); 00120 item = new wxMenuItem(menu, XRCID("cg_show_callgraph"), _("Show call graph"), _("Show call graph for selected/active project"), wxITEM_NORMAL); 00121 menu->Append(item); 00122 menu->AppendSeparator(); 00123 item = new wxMenuItem(menu, XRCID("cg_settings"), _("Settings..."), wxEmptyString, wxITEM_NORMAL); 00124 menu->Append(item); 00125 item = new wxMenuItem(menu, XRCID("cg_about"), _("About..."), wxEmptyString, wxITEM_NORMAL); 00126 menu->Append(item); 00127 // 00128 pluginsMenu->Append(wxID_ANY, _("CallGraph"), menu); 00129 00130 } 00131 00132 wxMenu* CallGraph::CreateProjectPopMenu() 00133 { 00134 wxMenu* menu = new wxMenu(); 00135 wxMenuItem *item(NULL); 00136 00137 item = new wxMenuItem(menu, XRCID("cg_show_callgraph"), _("Show call graph"), _("Show call graph for selected project"), wxITEM_NORMAL); 00138 menu->Append(item); 00139 00140 return menu; 00141 } 00142 00143 void CallGraph::HookPopupMenu(wxMenu *menu, MenuType type) 00144 { 00145 if (type == MenuTypeEditor) { 00146 //TODO::Append items for the editor context menu 00147 } else if (type == MenuTypeFileExplorer) { 00148 //TODO::Append items for the file explorer context menu 00149 } else if (type == MenuTypeFileView_Workspace) { 00150 //TODO::Append items for the file view / workspace context menu 00151 } else if (type == MenuTypeFileView_Project) { 00152 //TODO::Append items for the file view/Project context menu 00153 if ( !menu->FindItem( XRCID("cg_show_callgraph_popup") ) ) { 00154 menu->PrependSeparator(); 00155 menu->Prepend( XRCID("cg_show_callgraph_popup"), _("CallGraph"), CreateProjectPopMenu() ); 00156 } 00157 } else if (type == MenuTypeFileView_Folder) { 00158 //TODO::Append items for the file view/Virtual folder context menu 00159 } else if (type == MenuTypeFileView_File) { 00160 //TODO::Append items for the file view/file context menu 00161 } 00162 } 00163 00164 /*void CallGraph::UnHookPopupMenu(wxMenu *menu, MenuType type) 00165 { 00166 if (type == MenuTypeEditor) { 00167 //TODO::Unhook items for the editor context menu 00168 } else if (type == MenuTypeFileExplorer) { 00169 //TODO::Unhook items for the file explorer context menu 00170 } else if (type == MenuTypeFileView_Workspace) { 00171 //TODO::Unhook items for the file view / workspace context menu 00172 } else if (type == MenuTypeFileView_Project) { 00173 //TODO::Unhook items for the file view/Project context menu 00174 } else if (type == MenuTypeFileView_Folder) { 00175 //TODO::Unhook items for the file view/Virtual folder context menu 00176 } else if (type == MenuTypeFileView_File) { 00177 //TODO::Unhook items for the file view/file context menu 00178 } 00179 }*/ 00180 00181 00182 void CallGraph::UnPlug() 00183 { 00184 //TODO:: perform the unplug action for this plugin 00185 } 00186 00187 void CallGraph::OnAbout(wxCommandEvent& event) 00188 { 00189 //wxString version = wxString::Format(DBE_VERSION); 00190 00191 wxString desc = _("Create application call graph from profiling information provided by gprof tool. \n\n"); // zapsat vice info - neco o aplikaci dot 00192 desc << wxbuildinfo() << wxT("\n\n"); 00193 00194 wxAboutDialogInfo info; 00195 info.SetName(_("CallGraph")); 00196 info.SetVersion(_("v1.0")); 00197 info.SetDescription(desc); 00198 info.SetCopyright(_("2012 (C) Tomas Bata University, Zlin, Czech Republic")); 00199 info.SetWebSite(_("http://www.fai.utb.cz")); 00200 info.AddDeveloper(wxT("Václav Špruček")); 00201 info.AddDeveloper(wxT("Michal Bližňák")); 00202 00203 wxAboutBox(info); 00204 } 00205 00206 wxString CallGraph::GetGprofPath() 00207 { 00208 //ConfCallGraph confData; 00209 m_mgr->GetConfigTool()->ReadObject(wxT("CallGraph"), &confData); 00210 wxString gprofPath = confData.GetGprofPath(); 00211 00212 if(gprofPath.IsEmpty()) 00213 { 00214 #ifdef __WXMSW__ 00215 //gprof 00216 if (wxFileExists(wxT("C:") + stvariables::sd + wxT("MinGW-4.4.1") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::gprofname)) 00217 { 00218 gprofPath = wxT("C:") + stvariables::sd + wxT("MinGW-4.4.1") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::gprofname; 00219 } 00220 else if (wxFileExists(wxT("C:") + stvariables::sd + wxT("MinGW") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::gprofname)) 00221 { 00222 gprofPath = wxT("C:") + stvariables::sd + wxT("MinGW") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::gprofname; 00223 } 00224 else gprofPath = wxT(""); 00225 00226 #else 00227 if (wxFileExists(stvariables::sd + wxT("usr") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::gprofname)) 00228 { 00229 gprofPath = stvariables::sd + wxT("usr") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::gprofname; 00230 } 00231 else if (wxFileExists(stvariables::sd + wxT("usr") + stvariables::sd + wxT("local") + stvariables::sd + wxT("bin") + stvariables::gprofname)) 00232 { 00233 gprofPath = stvariables::sd + wxT("usr") + stvariables::sd + wxT("local") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::gprofname; 00234 } 00235 else gprofPath = wxT(""); 00236 #endif 00237 00238 confData.SetGprofPath(gprofPath); 00239 m_mgr->GetConfigTool()->WriteObject(wxT("CallGraph"), &confData); 00240 } 00241 00242 return gprofPath; 00243 } 00244 00245 wxString CallGraph::GetDotPath() 00246 { 00247 //ConfCallGraph confData; 00248 m_mgr->GetConfigTool()->ReadObject(wxT("CallGraph"), &confData); 00249 wxString dotPath = confData.GetDotPath(); 00250 00251 if(dotPath.IsEmpty()) 00252 { 00253 #ifdef __WXMSW__ 00254 // DOT 00255 if (wxFileExists(wxT("C:") + stvariables::sd + wxT("Graphviz 2.28") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname)) 00256 { 00257 dotPath = wxT("C:") + stvariables::sd + wxT("Graphviz 2.28") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname; 00258 } 00259 else if (wxFileExists(wxT("C:") + stvariables::sd + wxT("Graphviz") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname)) 00260 { 00261 dotPath = wxT("C:") + stvariables::sd + wxT("Graphviz") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname; 00262 } 00263 else if (wxFileExists(wxT("C:") + stvariables::sd + wxT("Program Files (x86)") + stvariables::sd + wxT("Graphviz 2.28") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname)) 00264 { 00265 dotPath = wxT("C:") + stvariables::sd + wxT("Program Files (x86)") + stvariables::sd + wxT("Graphviz 2.28") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname; 00266 } 00267 else dotPath = wxT(""); 00268 #else 00269 if (wxFileExists(stvariables::sd + wxT("usr") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname)) 00270 { 00271 dotPath = stvariables::sd + wxT("usr") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname; 00272 } 00273 else if (wxFileExists(stvariables::sd + wxT("usr") + stvariables::sd + wxT("local") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname)) 00274 { 00275 dotPath = stvariables::sd + wxT("usr") + stvariables::sd + wxT("local") + stvariables::sd + wxT("bin") + stvariables::sd + stvariables::dotname; 00276 } 00277 else dotPath = wxT(""); 00278 #endif 00279 00280 confData.SetDotPath(dotPath); 00281 m_mgr->GetConfigTool()->WriteObject(wxT("CallGraph"), &confData); 00282 } 00283 00284 return dotPath; 00285 } 00286 00287 void CallGraph::OnShowCallGraph(wxCommandEvent& event) 00288 { 00289 bool isgmonfile = false; 00290 bool isproject = false; 00291 bool issettings = false; 00292 00293 wxString errMsg, projectPath, projectPathActive, projectName, debugDirectory; 00294 debugDirectory = wxT("./Debug"); 00295 // 00296 m_mgr->GetConfigTool()->ReadObject(wxT("CallGraph"), &confData); 00297 // 00298 if (m_mgr->GetWorkspace()) 00299 { 00300 TreeItemInfo info = m_mgr->GetSelectedTreeItemInfo(TreeFileView); 00301 if( info.m_itemType == ProjectItem::TypeProject) projectName = info.m_text; 00302 else projectName = m_mgr->GetWorkspace()->GetActiveProjectName(); // get project name for active project 00303 00304 ProjectPtr proj = m_mgr->GetWorkspace()->FindProjectByName( projectName, errMsg ); 00305 if (proj) 00306 { 00307 BuildConfigPtr bldConf = m_mgr->GetWorkspace()->GetProjBuildConf(proj->GetName(), debugDirectory); 00308 if(bldConf) 00309 { 00310 debugDirectory = bldConf->GetIntermediateDirectory(); // ./Debug - name for intermediate folder 00311 } 00312 projectPath = proj->GetFileName().GetPath( wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR ); //path for selected/active project 00313 projectPathActive = projectPath; 00314 projectPath += debugDirectory + stvariables::sd; 00315 isproject = true; 00316 } 00317 else 00318 { 00319 wxMessageBox( errMsg, _("Error"), wxOK | wxICON_HAND ); 00320 } 00321 } 00322 if (wxFileExists(projectPath + stvariables::gmonfile)) 00323 { 00324 isgmonfile = true; 00325 } 00326 00327 if ((wxFileExists(GetGprofPath())) && (wxFileExists(GetDotPath()))) 00328 { 00329 issettings = true; 00330 } 00331 00332 if (isgmonfile && isproject && issettings) //check setting of the plugin 00333 { 00334 // start for parsing and writing to the dot language file 00335 bool candot = false; 00336 GprofParser *pgp = new GprofParser(); 00337 DotWriter *pdw = new DotWriter(); 00338 00339 wxProcess gprofProcess; 00340 gprofProcess.Redirect(); 00341 wxString cmdgprof = GetGprofPath() + stvariables::sw + stvariables::sq + projectPath + projectName + stvariables::filetype + stvariables::sq + stvariables::sw + stvariables::sq + projectPath + stvariables::gmonfile + stvariables::sq; 00342 wxExecute(cmdgprof, wxEXEC_SYNC, &gprofProcess); 00343 m_pInputStream = gprofProcess.GetInputStream(); 00344 00345 if(m_pInputStream->CanRead()) 00346 { 00347 pgp->GprofParserStream(m_pInputStream); 00348 candot = true; 00349 } 00350 else 00351 wxMessageBox(wxT("CallGraph failed to get profiling data, please build the project again."), wxT("CallGraph"), wxOK | wxICON_INFORMATION); 00352 // 00353 00354 if(candot) 00355 { 00356 //DotWriter to output png file 00357 pdw->setLineParser(&(pgp->lines)); 00358 pdw->setDotWriterFromDialogSettings(m_mgr);//(confData.GetColorsNode(),confData.GetColorsEdge(),confData.GetTresholdNode(),confData.GetTresholdEdge(),confData.GetBoxName(),confData.GetBoxParam()); 00359 // 00360 pdw->WriteToDotLanguade(); 00361 pdw->SendToDotAppOutputDirectory(projectPathActive); 00362 00363 if (pdw->DotFileExist(projectPathActive)) 00364 { //-Gcharset=Latin1 //UTF-8 00365 wxString cmddot = GetDotPath() + stvariables::sw + wxT("-Tpng -o") + stvariables::sw + projectPathActive + stvariables::dotfilesdir + stvariables::sd + stvariables::dotpngname + stvariables::sw + projectPathActive + stvariables::dotfilesdir + stvariables::sd + stvariables::dottxtname; 00366 wxProcess cmddotProcess; 00367 cmddotProcess.Redirect(); 00368 wxExecute(cmddot,wxEXEC_SYNC, &cmddotProcess); 00369 } 00370 else 00371 wxMessageBox(wxT("CallGraph failed to save file with DOT language, please build the project again."), wxT("CallGraph"), wxOK | wxICON_INFORMATION); 00372 } 00373 00374 //show image and greate table in the editor tab page 00375 if(wxFileExists(projectPathActive + stvariables::dotfilesdir + stvariables::sd + stvariables::dotpngname)) 00376 { 00377 m_mgr->AddEditorPage( new uicallgraphpanel( m_mgr->GetEditorPaneNotebook(), m_mgr, projectPathActive + stvariables::dotfilesdir + stvariables::sd + stvariables::dotpngname, &(pgp->lines)), wxT("Call graph for \"") + projectName + wxT("\"")); 00378 } 00379 else 00380 { 00381 wxMessageBox(wxT("Failed to open file CallGraph.png, please build the project and try this plugin again."), wxT("CallGraph"), wxOK | wxICON_INFORMATION); 00382 } 00383 00384 // delete objects 00385 delete pgp; 00386 pgp = 0; 00387 00388 delete pdw; 00389 pdw = 0; 00390 00391 } 00392 else 00393 { 00394 if (!isgmonfile) wxMessageBox(wxT("Please check if the selected/active project is compiled and linked with options \"-pg\" ."), wxT("CallGraph"), wxOK | wxICON_WARNING); 00395 else wxMessageBox(wxT("Please check settings for plugin."), wxT("CallGraph"), wxOK | wxICON_INFORMATION); 00396 } 00397 00398 } 00399 00400 void CallGraph::OnSettings(wxCommandEvent& event) 00401 { 00402 // open the settings dialog 00403 uisettingsdlg uisdlg(m_mgr->GetTheApp()->GetTopWindow(),m_mgr);//,this); 00404 uisdlg.ShowModal(); 00405 }